///********************************************************************
///* Copyright © 2011 fishr (fishr.flash@gmail.com)  
///********************************************************************
package su.fishr.effects 
{

	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	
	import su.fishr.effects.prismavision.PV_control;
   /**
	 *    Плагин - эффект Prismavision.
	 * @version                1.0
	 * @playerversion          Flash 9
	 * @langversion            3.0
	 * @author                 fishr
	 * @created                15.08.2011 17:28
	 * @since                  15.08.2011 17:28
	 */
	public  class Prismavision extends Sprite
	{
	
	///TODO: Сделать возможность останавливать и реверсировать
	/// начавшийся поворот призм.
	/**-------------------------------------------------------------------------------
	* 
	*	   						V A R I A B L E ' S 	
	* 
	* --------------------------------------------------------------------------------
	*/
	//{
        static public const AUTHOR:String = "fishr (fishr.flash@gmail.com)";	
		static public const END_ROTATION:String = "endRotation";
		
		private var _controll:PV_control;
		
		private var _arrImg:Array =  new Array();
		private var _wPrisma:int;
		private var _delay:Number = .1;
		private var _duration:Number;
		private var _senseOfRotate:int = 1;
		private var _verticalRotation:Boolean = false;
		private var _verticalOrient:Boolean = false;
		private var _manualStart:Boolean = false;
		private var _useFilters:Boolean = true;
		private var _nextNmElem:int = -1;
		
		private var _asyn:Number = 0;
		private var _countRows:int = 1;
		private var _blur:Number = 0;
		private var _gradient:Number = 0;
		private var _view:DisplayObject;
		private var _smoothing:int;
		private var _corrBrightness:Number = 1.5;
		private var _factorShadow:Number = 1.7;
		
		
	//}
	
	/**-------------------------------------------------------------------------------
	* 
	*	 						P R O P E R T I E S 	
	* 
	* --------------------------------------------------------------------------------
	*/
	//{
		
		public function get wPrisma():int 
		{
			return _wPrisma;
		}
		
		public function set wPrisma(value:int):void 
		{
			_wPrisma = value;
		}
		
		public function get delay():Number 
		{
			return _delay;
		}
		
		public function set delay(value:Number):void 
		{
			_delay = value;
		}
		
		public function get duration():Number 
		{
			return _duration;
		}
		
		public function set duration(value:Number):void 
		{
			_duration = value;
		}
		
		public function get senseOfRotate():int 
		{
			return _senseOfRotate;
		}
		
		public function set senseOfRotate(value:int):void 
		{
			_senseOfRotate = value;
		}
		
		public function get verticalRotation():Boolean 
		{
			return _verticalRotation;
		}
		
		public function set verticalRotation(value:Boolean):void 
		{
			_verticalRotation = value;
		}
		
		public function get asyn():Number 
		{
			return _asyn;
		}
		
		public function set asyn(value:Number):void 
		{
			_asyn = value;
		}
		
		public function get countRows():int 
		{
			return _countRows;
		}
		
		public function set countRows(value:int):void 
		{
			_countRows = value;
		}
		
		public function get blur():Number 
		{
			return _blur;
		}
		
		public function set blur(value:Number):void 
		{
			_blur = value;
		}
		
		public function get gradient():Number 
		{
			return _gradient;
		}
		
		public function set gradient(value:Number):void 
		{
			_gradient = value;
		}
		
		public function get verticalOrient():Boolean 
		{
			return _verticalOrient;
		}
		
		public function set verticalOrient(value:Boolean):void 
		{
			_verticalOrient = value;
		}
		
		public function get useFilters():Boolean 
		{
			return _useFilters;
		}
		
		public function set useFilters(value:Boolean):void 
		{
			_useFilters = value;
		}
		
		/**
		 *  Нормер следующего, за выведенным на сцену,
		 * элемента массива экр.объектов.
		 * Номер может быть произвольно измененн, но только
		 * после добавления объекта <code> Prismavision </code> на сцену.
		 */
		public function get nextNmElem():int 
		{
			return _controll.nextNbElem;
		}
		
		public function set nextNmElem(value:int):void 
		{
			_nextNmElem = value;
		}
		
		///TODO: Как сделать, чтобы каждый раз по сигн. руч. старта
		///во время поворота призм, по окночании поворота, сразу начинался следующий?
		
		public function get manualStart():Boolean 
		{
			return _manualStart;
		}
		
		/**
		 *  Возвращает статус приложения: true - активная фаза поворота призм, false - призмы неподвижны.
		 */
		public function get activeTurn():Boolean
		{
			return _controll.activeTurn;
		}
		
		public function get arrImg():Array 
		{
			return _arrImg;
		}
		
	//}
	/**-------------------------------------------------------------------------------
	* 
	*								P U B L I C 	
	* 
	* --------------------------------------------------------------------------------
	*/
	//{
		public function Prismavision( arrImg:Array, wPrisma:int, delay:Number, duration:Number, countRows:int = 1 )
		{
			super();
			init(null, arrImg, wPrisma, delay, duration, countRows );
		}
		
		/**
		 * Добавляет массив изображений к имеющемуся.
		 * @param	arrImg массив экр.объектов содержащий один и более елементов
		 * @param	replaced флаг замены массива, <code>false</code> ( по умолчанию ) - дополнить первоначальный
		 * <code>true</code> - заменить первоначальный
		 */
		public function uploadImages( arrImg:Array, replaced:Boolean = false ):void
		{
			_controll.replacedImages = replaced;
			_arrImg = _arrImg.concat( arrImg );
				
		}
		
		/**
		 *  "Ручной" старт поворота призм.
		 * При указании необязательного параметра <code>manual</code>
		 * со значением <code>false</code> отключает режим "ручного"
		 * старта поворота призм, возвращая автоматический поворот согласно
		 * указанной задержки <code>Prismavision.delay()</code>.
		 * 
		 * @param	manual необязательный параметр, значение <code>true</code>  ( по умолчанию ) 
		 * 			отключает режим автоповорота призм.
		 * 
		 */
		public function replaceStart(manual:Boolean = true):void
		{
			if ( manual === false && _manualStart === false ) return;
			_controll.manualStart = _manualStart = manual;
		}
		
		public function selectFilters( smoothing:int = 1, corrBrightness:Number = 1, factorShadow:Number = 1 ):void
		{
			_smoothing = smoothing;
			_corrBrightness = corrBrightness;
			_factorShadow = factorShadow;
			
			
		}
	//}
	
	/**-------------------------------------------------------------------------------
	* 
	*								P R I V A T E 	
	* 
	* --------------------------------------------------------------------------------
	*/	
	//{
		
		private function init(e:Event, arrImg:Array = null, wPrisma:int = 0, delay:Number = 0, duration:Number = 0, countRows:int = 0):void
		{
			_arrImg = arrImg?arrImg:_arrImg;
			_wPrisma = wPrisma?wPrisma:_wPrisma;
			_delay = delay?delay:_delay;
			_duration = duration?duration:_duration;
			_countRows = countRows?countRows:_countRows;
			
			
			_controll = new PV_control();
			_controll.addEventListener( PV_control.UPLOAD_PARAM, uploadParamHandler);
			_controll.addEventListener( PV_control.END_ROTATION, endRotationHandler);
			_view = _controll.view;

			this.addChild( _view );
			
			if ( stage ) uploadParamHandler( null );
			else this.addEventListener( Event.ADDED_TO_STAGE, uploadParamHandler );
			
			///TODO: Пока дестроеры отключены
			this.addEventListener( Event.REMOVED_FROM_STAGE, destroyThisHandler );
		}
		
		private function endRotationHandler(e:Event):void 
		{
			_controll.addEventListener( PV_control.UPLOAD_PARAM, uploadParamHandler);
			this.dispatchEvent( new Event( END_ROTATION ) );
		}
		
		private function uploadParamHandler(e:Event):void 
		{
			
			var fps:int = this.stage.frameRate;
			this.removeEventListener( Event.ADDED_TO_STAGE, uploadParamHandler );
			this.visible = true;
			///изменения параметров модели
			_controll.delay = _delay;
			
			_controll.wPrisma = _wPrisma;
			_controll.countRows = _countRows;
			_controll.fps = fps;
			_controll.useFilters = _useFilters
			_controll.duration = _duration;
			_controll.verticalOrient = _verticalOrient;
			_controll.smooth = _smoothing;
			_controll.corrBrightness = _corrBrightness;
			_controll.factorShadow = _factorShadow;
			_controll.nextNbElem = _nextNmElem;
			///возвращаем неопределенное состояние пер-ной
			///для того чтобы не было воспринято как измен. значения.
			_nextNmElem = -1;
			///изменения парам. вьюера
			_controll.senseOfRotate = _senseOfRotate;
			
			_controll.verticalRotation = _verticalRotation;
			
			///сразу преобразуем время задержки в кол-во
			///кадров задержки.
			_controll.asyn = fps * _asyn;
			_controll.blur = _blur;
			_controll.gradient = _gradient;
			///завершает цикл обновления параметров
			///по обращении к сеттеру модели генерится
			///сигнал обновления.
			_controll.arrImg = _arrImg;
			
			
			_controll.addEventListener( PV_control.END_ROTATION, endRotationHandler);
			this.addEventListener( Event.REMOVED_FROM_STAGE, destroyThisHandler );

		}
		
		private function destroyThisHandler(e:Event):void 
		{

			this.removeEventListener(Event.REMOVED_FROM_STAGE, destroyThisHandler);
			_controll.removeEventListener( PV_control.UPLOAD_PARAM, uploadParamHandler);
			_controll.removeEventListener( PV_control.END_ROTATION, endRotationHandler);
			this.addEventListener( Event.ADDED_TO_STAGE, init );
			while ( this.numChildren ) this.removeChildAt(0);
			this._arrImg = _controll.arrImg;
			this.visible = false;
			_nextNmElem = _controll.nextNbElem;
			_controll.destroyObjects();
			_controll = null;

		}
		

		

	//}

	}

}